// Encoding documentation:
// https://en.wikipedia.org/wiki/Code_39#Encoding

import Barcode from '../Barcode.js';

class CODE39 extends Barcode {
  constructor(data, options) {
    data = data.toUpperCase();

    // Calculate mod43 checksum if enabled
    if (options.mod43) {
      data += getCharacter(mod43checksum(data));
    }

    super(data, options);
  }

  encode() {
    // First character is always a *
    var result = getEncoding('*');

    // Take every character and add the binary representation to the result
    for (let i = 0; i < this.data.length; i++) {
      result += getEncoding(this.data[i]) + '0';
    }

    // Last character is always a *
    result += getEncoding('*');

    return {
      data: result,
      text: this.text
    };
  }

  valid() {
    return this.data.search(/^[0-9A-Z\-\.\ \$\/\+\%]+$/) !== -1;
  }
}


// All characters. The position in the array is the (checksum) value
var characters = [
  '0', '1', '2', '3',
  '4', '5', '6', '7',
  '8', '9', 'A', 'B',
  'C', 'D', 'E', 'F',
  'G', 'H', 'I', 'J',
  'K', 'L', 'M', 'N',
  'O', 'P', 'Q', 'R',
  'S', 'T', 'U', 'V',
  'W', 'X', 'Y', 'Z',
  '-', '.', ' ', '$',
  '/', '+', '%', '*'
];

// The decimal representation of the characters, is converted to the
// corresponding binary with the getEncoding function
var encodings = [
  20957, 29783, 23639, 30485,
  20951, 29813, 23669, 20855,
  29789, 23645, 29975, 23831,
  30533, 22295, 30149, 24005,
  21623, 29981, 23837, 22301,
  30023, 23879, 30545, 22343,
  30161, 24017, 21959, 30065,
  23921, 22385, 29015, 18263,
  29141, 17879, 29045, 18293,
  17783, 29021, 18269, 17477,
  17489, 17681, 20753, 35770
];

// Get the binary representation of a character by converting the encodings
// from decimal to binary
function getEncoding(character) {
  return getBinary(characterValue(character));
}

function getBinary(characterValue) {
  return encodings[characterValue].toString(2);
}

function getCharacter(characterValue) {
  return characters[characterValue];
}

function characterValue(character) {
  return characters.indexOf(character);
}

function mod43checksum(data) {
  var checksum = 0;
  for (let i = 0; i < data.length; i++) {
    checksum += characterValue(data[i]);
  }

  checksum = checksum % 43;
  return checksum;
}

export {CODE39};
